hello,JS:06-4 ES5 数组拓展

一、针对Array对象做了大幅拓展

1、Array.isArray(obj)

用于判断一个变量(或对象)是否为数组,如:

1
2
3
4
5
Array.isArray([])
// true

Array.isArray({})
// false

2、.indexOf(element) / .lastIndexOf(element)

用于如何判断在一个数组中找到所看到的一个值、数字,或变量是否存在
(1)ES3的做法:

1
2
3
4
5
6
7
8
9
10
11
12
13
         var arr =  [3,  4,  'hello'  ,'wangxiaoqin'] 
// undefined
function hasWord(arr,item){ for(var i=0; i<arr.length; i++){
if(arr[i] === item)
return true
}
return false
}
// undefined
hasWord(arr,'wangxiaoqin')
// true
hasWord(arr,'helloo')
// false

(2)ES5的拓展做法

1
2
3
4
5
6
var arr =  [3,  4,  'hello'  ,'wangxiaoqin'] 
// undefined
arr.indexOf('wangxiaoqin')
// 3
arr.indexOf('wanxiaoqin')
// -1 //写了一个不存在的,直接输出-1

总结:
那么,依此可以得出,-1也可以作为判断某对象是否存在于该数组

3、.forEach(element,index,arrary)

遍历一个数组,可以使用for循环;也可以数组自带的.forEach

1
2
3
4
5
6
7
8
9
10
11
var arr =  [3,  4,  'hello'  ,'wangxiaoqin'] 
// undefined
arr
--> (4) [3, 4, "hello", "wangxiaoqin"]
arr.forEach(function(){
console.log(arguments)
})
-->Arguments(3) [3, 0, Array(4),
Arguments(3) [4, 1, Array(4),
Arguments(3) ["hello", 2, Array(4),
Arguments(3) ["wangxiaoqin", 3, Array(4),

图:
image
接着,可以使用.forEach遍历该数组

1
2
3
4
5
6
7
8
arr.forEach(function(value,index){  //value指数组中的元素,index指数组中的下标 
console.log(''+value+value)
})
-->33
44
hellohello
wangxiaoqinwangxiaoqin
//undefined

4、.every(function(element, index, array))

用于满足该数组中函数设定的某个条件,函数返回的是一个布尔值
满足条件:

  • every是所有函数的每个回调函数都返回true的时候才会返回true,当遇到false的时候终止执行,返回false
  • some函数是“存在”有一个回调函数返回true的时候终止执行并返回true,否则返回false
    如:
    1
    2
    3
    4
    [3,4,-1,0,5].every(function(val){ 
    return val>0?true:false //使用三目运算符 === if...else
    })
    // false

.some(function(element,index,array))只要有一个符合,那就返回true;反之,则..

5、.map(function(element))

对数组中每一元素进行处理,函数返回值组成一个新数组返回,新数组索引结构和原数组一致,原数组保持不变。

1
2
3
4
5
6
var arr2 =  [1,  2,  3,  4,  5,  6].map(function(val){ 
return val*val
})
// undefined
arr2
// (6) [1, 4, 9, 16, 25, 36]

6、
1
2
3
4
5
数组的过滤。

**注:**

产生新数组,原数组保持不变,如:

var arr=[3, 5, 6, -1, -2, -3]
// undefined
arr.filter(function(val){
return val>0
})
// (3) [3, 5, 6] //产生新数组
arr
// (6) [3, 5, 6, -1, -2, -3] //原数组不变

/ 所以,我们需要为新数组赋新变量 /
var arr2 = arr.filter(function(val){
return val>0
})
// undefined
arr2
// (3) [3, 5, 6]

/ 如需过滤出里面的负数 /
var arr3 = arr.filter(function(val){
return val <0
})
// undefined
arr3
// (3) [-1, -2, -3]

1
再如:

var students = [
{
name:’ad’,
age:10
},
{
name:’bb’,
age:20
},
{
name:’ca’,
age:8
},
{
name:’ce’,
age:5
},
]

/ 假设过滤出数组里年纪大于18岁的 /
var age18 =
students.filter(function(students){
return students.age > 18
})
console.log(age18)

--> [[object Object]  {
            age:  20,
            name:  "bb"hui
           }
 ] 

/ 假设过滤出数组里姓名里带有“c” /
var namehasc =
students.filter(function(students){
return students.name.indexOf(‘c’)>-1
})
console.log(namehasc)
–>[[object Object] {
age: 8,
name: “ca”
}, [object Object] {
age: 5,
name: “ce”
}]

1
2
3
4
以此,可以通过过滤可进行排序、查找、单独的处理

### 7、`.reduce(function(v1, v2), value)`
两元素(或参数)执行操作,数组元素返回组合成一个值,遍历数组,继续和数组中 其他元素组合,最终得出结果。代码如下:

var arr = [3, 4, 5]
–> undefined
arr.reduce(function(v1,v2){
return v1 + v2
})
–> 12 //7+5
arr.reduce(function(v1,v2){
return v1 v2
})
–> 60 //12
5

/ 使用初始值 .reduce(function(v1, v2), value) value为初始值 /
arr.reduce(function(v1,v2){
return v1 + v2 },100)
–> 112

//100(v1)+3(v2)+4+5
//103(v1)+4(v2)+5
以此类推

1
2
3
4
5
6
7
8

# 二、学习
### 1、手写reduce功能
A、先补充一些基本JS知识,

假设:想要克隆一个与`arr`完全一样的`arr2`,但二者互不相干,如何处理?通过使用concat方法,一个数组arr拼接另一个数组,然后得到一个新的数组`arr2`。即通过concat获得一个新数组,拼接的原数组保持不变。实现一个**深拷贝**。

**注:[ ]空数组也是一个数组**

arr = [1,2,3]
// [1, 2, 3]
arr2 = arr.concat([])
// [1, 2, 3]
arr2
// [1, 2, 3]

/ 测试一下是否二者有关联 /
arr2[0] = 100
// 100
arr
// [1, 2, 3]
arr2
// [100, 2, 3]

1
2

B、手写一个reduce功能

function reduce(arr, fn, initValue){
var arr2 = arr //===[3, 4, 5, 6]
while(arr2.length > 1)
}
//第2:如何是实现reduce?计划通过处理arr2 = [3, 4, 5, 6]的v1,v2, 通过function(v1,v2){return v1+v2}处理,依次循环得出结果

var arr = [3, 4, 5, 6]
var result = reduce(arr, function(v1,v2){
return v1+v2 //第1:通过此遍历arr数组
},10)

1
取消初始值去做:

function reduce(arr, fn){
var arr2 = arr //===[3, 4, 5, 6]
while(arr2.length > 1){
console.log(arr2)
arr2.splice(0,2,fn(arr2[0],arr2[1]))
}
return arr2[0]
} //第3:while(arr2.length > 1) 相当于设置一个条件:当这个数组有两个以上的值时,
//第4:arr2 === arr用fn函数进行处理,v1+v2相加替换成一个结果, 使用splice(位数,个数,替换的结果),依次类推得出arr2 === arr的结果

       var arr =  [3,  4,  5,  6]  
              //[7,5,6]  
             //[12,6]  
            //[18]  
      var result =  reduce(arr,  function(v1,v2){ 
                     return v1+v2
               })
          console.log(result)  

//输出结果  
      -->[3,  4,  5,  6]  
           [7,  5,  6] 
           [12,  6]  
           18
1
2
3
4
5
6
7
8
图:
![image](https://user-gold-cdn.xitu.io/2018/8/15/1653d54a94608a6e?w=600&h=375&f=jpeg&s=31303)
但是,这里有个问题,就是`arr2===arr`,却没有实现二者互不相关。如何处理?如图:
![image](https://user-gold-cdn.xitu.io/2018/8/15/1653d54a9487c395?w=600&h=250&f=jpeg&s=22572)
可以通过: 原始数组`.concat([])`组合成一个新数组,且原数组与之无关。如图:
![image](https://user-gold-cdn.xitu.io/2018/8/15/1653d54a94983a00?w=600&h=288&f=jpeg&s=26717)

添加初始值之后,该如何做呢?

function reduce(arr, fn,initValue){
var arr2 = arr.concat([]) //===[3, 4, 5, 6]
if(initValue !== undefined){ //这里注意 === 会出现报错
arr2.unshift(initValue)
}
//不等于undefined,表示用户传递了这个initValue参数

   while(arr2.length >  1){
              console.log(arr2) 
              arr2.splice(0,2,fn(arr2[0],arr2[1]))  
       } 
         return arr2[0]  
 }  

var arr =  [3,  4,  5,  6]  
var result =  reduce(arr,  function(v1,v2){  
             return v1 + v2 },10) 
             console.log(result)  

//输出值:
–> [10, 3, 4, 5, 6]
[13, 4, 5, 6]
[17, 5, 6]
[22, 6]
28

1
2
3
图:
![image](https://user-gold-cdn.xitu.io/2018/8/15/1653d54a94b9cf5e?w=600&h=348&f=jpeg&s=30881)
或者减少代码量,采用三目运算符的方法来设置初始值:

function reduce(arr, fn,initValue){
var arr2 =
(initValue !== undefined?[]:[initValue]).concat(arr)
while(arr2.length > 1){
console.log(arr2)
arr2.splice(0,2,fn(arr2[0],arr2[1]))
}
return arr2[0]
}

var arr =  [3,  4,  5,  6]  
var result =  reduce(arr,  function(v1,v2){ 
            return v1 + v2 },10) 
            console.log(result)  

//输出值
–> [3, 4, 5, 6]
[7, 5, 6]
[12, 6]
18

1
2
3
4
5
6
7
图:
![image](https://user-gold-cdn.xitu.io/2018/8/15/1653d54a94b5b19f?w=600&h=283&f=jpeg&s=23154)

### 2、将一个数组拍平
对一个无限次嵌套的数组进行拍平,如何处理?

例子1:这道题也可以作为一个初级JS的思考,每次不会做的话,先从这道题的基本思考方式来看

var arr = [3, [‘4,5’,7,[1]], [2,10] ]
function flat(){
} //重点解决这一块的逻辑,即最终返回一个新的数组
var arr2 = flat(arr)

console.log(arr2) 

var arr = [3, [‘4,5’,7,[1]], [2,10] ]
function flat(arr){
var arr2 = []
arr.forEach(function(val){
if(Array.isArray(val)){
arr2 =arr2.concat(flat(val))
}else{
arr2.push(val)
}
})
return arr2//不是数组的话就返回 }

/ flat(arr)就是将一个数组拍平,变成一个普通数组,对arr里进行判断, 如果不是个数组(如3),则放在 var arr2 = []里的空数组里, 如果是数组的,即 [‘4,5’,7,[1]],则把其放在这个arr.forEach(function(val){})数组里执行,则 重点解决函数这一块的逻辑 :
1、定义一个要返回的数组arr2
2、遍历原始数组arr,且用函数遍历arr的每一项
2.1 if判断是否为数组,采用Array.isArray判断。 若是数组,要处理嵌套数组,再次调用函数,将嵌套函数“拍平”,用递归法一一验证,最后得出结果
2.2 else如果不是数组,直接push在arr=[]里
/

var arr2 = flat(arr) console.log(arr2)

//输出结果
–> [3, “4,5”, 7, 1, 2, 10]

1
2
3

例子2:
实现一个flatten函数,将一个嵌套多层的数组arry(数组)(嵌套可以是任何层数)转换成只有一层的数组,数组中元素仅基本类型的元素或数组,不存在循环引用的情况。如:

flatten([1,[2],[3,[[4]]])=> [1,2,3,4]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
```
var arr = [3,[2,-4,[5,7]],-3,['aa',[['bb']]]]
var arr2 = flatten2(arr)
console.log(arr2)

/* 方法1: */
function flatten(arr){
var newArr = []
function _flat(arr){
arr.forEach(val=>{ //对数组的每一项进行一个遍历 val=>,为匿名函数
if(Array.isArray(val)){
_flat(val)
}else{
newArr.push(val)
}
})
}
_flat(arr)
return newArr }

/* 方法2: */

function flatten2(arr){
return arr.reduce(function(initArr,currentArr){
return initArr.concat(Array.isArray(currentArr)?flatten2(currentArr):currentArr)
},[])
}

/*不是数组的话,就concat;如果是数组,则通过再次调用flatten2(Arr)拍平当前数组flatten2(currentArr) */

-------------本文结束感谢您的阅读-------------